﻿using System.Collections.Concurrent;
using System.Diagnostics;
using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using MG.Repository;
using MG.SmartHMI.Common;
using MG.SmartHMI.Domain;
using MG.SmartHMI.Entity.DAO;
using MG.SmartHMI.Model;
using MG.SmartHMI.Model.Common;
using MG.SmartHMI.Model.Common.Enum;
using MG.Util.Log;
using SqlSugar;

namespace MG.SmartHMI.ViewModel
{
    public partial class HomeViewModel : ObservableRecipient
    {
        #region parm

        [ObservableProperty]
        private List<string> slnResource;

        [ObservableProperty]
        private string selectedSlnName;

        [ObservableProperty]
        private List<ButtonViewModel> listPrimaryButton;

        [ObservableProperty]
        private List<ButtonViewModel> listButton;

        [ObservableProperty]
        private List<CheckBoxViewModel> listCheckBox;

        [ObservableProperty]
        private List<SwitchViewModel> listSwitch;

        [ObservableProperty]
        private List<InputSignalViewModel> listInputSignal;

        [ObservableProperty]
        private List<DispBoxViewModel> listDispBox;

        [ObservableProperty]
        private bool visiblityPrimaryButton;

        [ObservableProperty]
        private bool visiblityButton;

        [ObservableProperty]
        private bool visiblityCheckBox;

        [ObservableProperty]
        private bool visiblitySwitch;

        [ObservableProperty]
        private bool visiblityInputSignal;

        [ObservableProperty]
        private bool visiblityDispBox;

        private ConcurrentDictionary<int, MessageStateConfig> DictMessage = new();

        private string StateMeageAddress = string.Empty;

        private static int PreStateCode = 0;

        private int CurrSlnId;

        partial void OnSelectedSlnNameChanged(string value)
        {
            //配方数据值写入到下位机
            CurrSlnId = RepositoryService<SlnConfig>.Instance.Query(t => t.Name.Equals(value) && !t.IsDelete).FirstOrDefault()?.Id ?? 0;

            Task.Run(() => WriteSln(CurrSlnId));
            RepositoryService<Config>.Instance.UpdateFiled(t => new Config() { Value = CurrSlnId.ToString() }, q => q.Key.Equals("LastSlnId"));
        }

        #endregion parm

        #region construct

        public HomeViewModel()
        {
            Register();
        }

        #endregion construct

        #region Other

        private void Update2UI()
        {

            #region 控件更新

            var listregister = RepositoryService<RegisterConfig>.Instance.Query(t => t.Disp_MainView && !t.IsDelete).OrderBy(t2 => t2.SortLevel).ToList();
            List<ButtonViewModel> primbuttons = new();
            List<ButtonViewModel> normbuttons = new();
            List<CheckBoxViewModel> checks = new();
            List<SwitchViewModel> switchs = new();
            List<InputSignalViewModel> inputsignales = new();
            List<DispBoxViewModel> dispboxes = new();

            foreach (var item in listregister)
            {
                switch (item.ControlType)
                {
                    case EnumControlType.Switch:
                        switchs.Add(new SwitchViewModel(item));
                        break;

                    case EnumControlType.InputSignal:
                        inputsignales.Add(new InputSignalViewModel(item));
                        break;

                    case EnumControlType.CheckBox:
                        checks.Add(new CheckBoxViewModel(item));
                        break;

                    case EnumControlType.DispDataBox:
                        dispboxes.Add(new DispBoxViewModel(item));
                        break;

                    case EnumControlType.NormButton:
                        normbuttons.Add(new ButtonNormViewModel(item));
                        break;

                    case EnumControlType.StartButton:
                        primbuttons.Add(new ButtonStartViewModel(item));
                        break;

                    case EnumControlType.EmgButton:
                        primbuttons.Add(new ButtonEmgViewModel(item));
                        break;

                    case EnumControlType.StopButton:
                        primbuttons.Add(new ButtonStopViewModel(item));
                        break;

                    case EnumControlType.PauseButton:
                        primbuttons.Add(new ButtonPauseViewModel(item));
                        break;

                    case EnumControlType.ResetButton:
                        primbuttons.Add(new ButtonResetViewModel(item));
                        break;

                    case EnumControlType.InputBox:
                    default:
                        break;
                }
            }

            ListPrimaryButton = primbuttons;
            ListButton = normbuttons;
            ListCheckBox = checks;
            ListSwitch = switchs;
            ListInputSignal = inputsignales;
            ListDispBox = dispboxes;

            VisiblityPrimaryButton = ListPrimaryButton.Count() > 0;
            VisiblityButton = ListButton.Count() > 0;
            VisiblityCheckBox = ListCheckBox.Count() > 0;
            VisiblitySwitch = ListSwitch.Count() > 0;
            VisiblityInputSignal = ListInputSignal.Count() > 0;
            VisiblityDispBox = ListDispBox.Count() > 0;

            StateMeageAddress = RepositoryService<Config>.Instance.Query(t => t.Key.Equals("MonitoringAddress") && !t.IsDelete).First().Value;
            DictMessage.Clear();
            RepositoryService<MessageStateConfig>.Instance.Query(t => !t.IsDelete).ForEach(q => DictMessage.TryAdd(q.StateCode, q));

            #endregion 控件更新

            #region SLN

            SlnResource = RepositoryService<SlnConfig>.Instance.Query(t => !t.IsDelete).Select(q => q.Name).ToList();
            CurrSlnId = int.Parse(RepositoryService<Config>.Instance.Query(t => t.Key.Equals("LastSlnId") && !t.IsDelete).FirstOrDefault().Value);
            SelectedSlnName = RepositoryService<SlnConfig>.Instance.Query(t => t.Id.Equals(CurrSlnId) && !t.IsDelete).FirstOrDefault()?.Name;

            #endregion SLN

            #region 地址范围传递给MDOBUSCTRL

            List<RegisterConfig> list = new List<RegisterConfig>();
            list.AddRange(inputsignales.Select(t => t.RegisterData));
            list.AddRange(dispboxes.Select(t => t.RegisterData));

            ModbusCtrl.Instance.UpdateBatchData(list);

            #endregion 地址范围传递给MDOBUSCTRL  

        }

        private void InitUI()
        {
            ListCheckBox.ForEach(t => t.UpdateRead());
            ListSwitch.ForEach(t => t.UpdateRead());
        }

        private void Register()
        {
            WeakReferenceMessenger.Default.Register<string, string>(this, "HomeViewLoadSignal", ViewLoadSlot);
            WeakReferenceMessenger.Default.Register<string, string>(this, "HomeViewUnLoadSignal", ViewUnLoadSlot);
        }

        private void CircleTimeActionSlot()
        {
            Task.Run(() =>
            {
                var batchres = ModbusCtrl.Instance.BatchRead();
                var boolres = ModbusCtrl.Instance.BatchReadBool();
                if (batchres.IsSuccess && boolres.IsSuccess)
                {
                    var datares = batchres.Content;
                    var databoolres = boolres.Content;
                    ListDispBox.ForEach(t => t.ParsebyBatchData(ref datares, ref databoolres));
                    ListInputSignal.ForEach(t => t.ParsebyBatchData(ref datares, ref databoolres));
                }

                logMessageState();
            });
        }

        private void ViewUnLoadSlot(object recipient, string message)
        {
            EventBus.Default.UnBindCircleTimeAction(CircleTimeActionSlot);
        }

        private void ViewLoadSlot(object recipient, string message)
        {

            Task.Run(() =>
            {
                EventBus.Default.BindCircleTimeAction(CircleTimeActionSlot);
                Update2UI();
                InitUI();
            });
        }

        private void logMessageState()
        {
            if (MessageStateChanged(out int NewStateCode))
            {
                var res = DictMessage.TryGetValue(NewStateCode, out MessageStateConfig msagecfg);
                if (!res) return;
                switch (msagecfg.MessageLevel)
                {
                    case EnumMessageLevel.Info:
                        EventBus.Default.Log(new LogInfo($"状态码[{NewStateCode}]      信息：{msagecfg.Message}"));
                        break;

                    case EnumMessageLevel.Warn:
                        EventBus.Default.Log(new LogInfo($"状态码[{NewStateCode}]      信息：{msagecfg.Message}", LogLevel.Warn));
                        break;

                    case EnumMessageLevel.Pop:
                        EventBus.Default.Log(new LogInfo($"状态码[{NewStateCode}] 信息：{msagecfg.Message}", LogLevel.Error));
                        App.Current.Dispatcher.BeginInvoke(() =>
                        {
                            MessageBox.Show(msagecfg.Message, "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                        });
                        break;
                }
            }
        }

        private bool MessageStateChanged(out int NewCode)
        {
            int oldcode = PreStateCode;
            NewCode = int.Parse(ModbusCtrl.Instance.UnitRead(EnumDataType.SHORT, StateMeageAddress).Content);
            Debug.WriteLine($"NewCode{NewCode}");
            PreStateCode = NewCode;
            return NewCode != oldcode;
        }

        private void WriteSln(int slnid)
        {
            List<CheckBoxViewModel> checks = new();
            List<SwitchViewModel> switchs = new();
            List<InputBoxViewModel> inputboxes = new();

            #region 从配方数据库中取出数据

            //查出SlnParm的值
            var listSlnParm = RepositoryService<SlnParmConfig>.Instance.Query(t => t.SlnId.Equals(slnid) && !t.IsDelete);

            //查出Sln界面的寄存器
            var listregister = RepositoryService<RegisterConfig>.Instance.Query(t => t.Disp_SlnView && !t.IsDelete);
            foreach (var item in listregister)
            {
                string slndata = string.Empty;
                foreach (var itemparm in listSlnParm)
                {
                    if (item.Id.Equals(itemparm.RegisterId))
                    {
                        ModbusCtrl.Instance.UnitWrite(item.DataType, item.Address, itemparm.Value);
                        break;
                    }
                }
            }

            EventBus.Default.Log(new LogInfo($"配方 [{SelectedSlnName}] 写入"));

            #endregion 从配方数据库中取出数据
        }

        #endregion Other
    }
}